package com.sunther.document.util;

import com.sunther.idb.common.util.StrUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author :Oliver
 * @time :2017\11\22 0022.
 */
public class FileUtil {
    public static final int FILE_BUFF_SIZE = 65536;
    public static final int PROGRESS_ACTION_ID = 900;
    private static Logger log = LoggerFactory.getLogger(FileUtil.class);

    public FileUtil() {
    }

    public static boolean supportedTypes(String ext){
        if (StrUtil.isEqual("rar",ext)) {
            return true;
        }else if (StrUtil.isEqual("zip",ext)) {
            return true;
        }else if (StrUtil.isEqual("doc",ext)) {
            return true;
        }else if (StrUtil.isEqual("docx",ext)) {
            return true;
        }else if (StrUtil.isEqual("pdf",ext)) {
            return true;
        }else if (StrUtil.isEqual("xls",ext)) {
            return true;
        }else if (StrUtil.isEqual("xlsx",ext)) {
            return true;
        }else {
            return false;
        }
    }

    public static boolean createFolderTree(String path) {
        boolean result = true;
        if (path.endsWith("/")||path.endsWith("\\")){
            path=path.substring(0,path.length()-1);
        }
        try {
            File f = new File(path);
            if (f.exists()) {
                return true;
            }

            f.mkdirs();
        } catch (Exception var3) {
            log.warn("", var3);
            result = false;
        }

        return result;
    }

    public static int copyFile(InputStream is, String destFile, long fileSize, ActionListener listener) {
        byte result = 0;

        try {
            OutputStream out = new FileOutputStream(destFile);
            byte[] buf = new byte[65536];
            //int progress = false;
            long writedLen = 0L;

            int len;
            while ((len = is.read(buf)) > 0) {
                out.write(buf, 0, len);
                writedLen += (long) len;
                if (listener != null && fileSize > 0L) {
                    int progress = (int) (writedLen * 100L / fileSize);
                    ActionEvent ae = new ActionEvent(FileUtil.class, 900, String.valueOf(progress));
                    listener.actionPerformed(ae);
                }
            }

            out.close();
            is.close();
        } catch (Exception var13) {
            log.warn("", var13);
            result = -1;
        }

        return result;
    }

    public static String getFileName(String filePathName) {
        if (StrUtil.isEmpty2(filePathName)) {
            return "";
        } else {
            filePathName = filePathName.trim();
            int pos1 = filePathName.lastIndexOf("/");
            int pos2 = filePathName.lastIndexOf("\\");
            int pos = pos1 > pos2 ? pos1 : pos2;
            return pos >= 0 ? filePathName.substring(pos + 1) : filePathName;
        }
    }

    public static String[] getFilePathName(String filePathName) {
        String[] data = new String[]{"", ""};
        if (StrUtil.isEmpty2(filePathName)) {
            return data;
        } else {
            filePathName = filePathName.trim();
            int pos1 = filePathName.lastIndexOf("/");
            int pos2 = filePathName.lastIndexOf("\\");
            int pos = pos1 > pos2 ? pos1 : pos2;
            if (pos == filePathName.length() - 1) {
                data[0] = filePathName;
                data[1] = "";
            } else if (pos >= 0) {
                data[0] = filePathName.substring(0, pos + 1);
                data[1] = filePathName.substring(pos + 1);
            } else {
                data[0] = "";
                data[1] = filePathName;
            }

            return data;
        }
    }

    public static String getFileExt(String pathFileName) {
        String fileName = getFileName(pathFileName);
        if (StrUtil.isEmpty2(fileName)) {
            return "";
        } else {
            int pos = pathFileName.lastIndexOf(".");
            return pos >= 0 ? pathFileName.substring(pos + 1) : "";
        }
    }

    public static String appendFileName(String path, String fileName) {
        path = StrUtil.safeTrim2(path);
        fileName = StrUtil.safeTrim2(fileName);
        boolean b1 = false;
        boolean b2 = false;
        if (StrUtil.isEmpty(path)) {
            return fileName;
        } else if (StrUtil.isEmpty(fileName)) {
            return path;
        } else {
            String suffix = path.substring(path.length() - 1);
            if ("/".equals(suffix) || "\\".equals(suffix)) {
                b1 = true;
            }

            String prefix = fileName.substring(0, 1);
            if ("/".equals(prefix) || "\\".equals(prefix)) {
                b2 = true;
            }

            if (b1 && b2) {
                return path + fileName.substring(1);
            } else {
                return !b1 && !b2 ? path + "/" + fileName : path + fileName;
            }
        }
    }

    public static String appendFileExt(String fileName, String ext) {
        fileName = StrUtil.safeTrim2(fileName);
        ext = StrUtil.safeTrim2(ext);
        return StrUtil.isEmpty2(ext) ? fileName : fileName + "." + ext;
    }

    public static boolean deleteFile(String filePathName) {
        File file = new File(filePathName);
        if (file.exists() && !file.isDirectory()) {
            file.delete();
            return true;
        } else {
            return false;
        }
    }

    public static List<String> readTextFile(String filePathName) throws FileNotFoundException, IOException {
        List<String> lines = new ArrayList();
        InputStreamReader reader = null;
        BufferedReader br = null;
        FileInputStream input = null;

        try {
            input = new FileInputStream(filePathName);
            reader = new InputStreamReader(input);
            br = new BufferedReader(reader);

            String line;
            while ((line = br.readLine()) != null) {
                lines.add(line);
            }
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException var17) {
                ;
            }

            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException var16) {
                ;
            }

            try {
                if (input != null) {
                    input.close();
                }
            } catch (IOException var15) {
                ;
            }

        }

        return lines;
    }

    /**
     * 将上传文件转为InputStream
     *
     * @param file
     * @return
     */
    public static InputStream fileToStream(MultipartFile file) throws Exception{
        InputStream stream = null;
        stream = file.getInputStream();
        return stream;
    }

    public static MultipartFile streamToFile(InputStream inputStream, String fileName) throws Exception{
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {
            log.error("Stream copy exception", e);
            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);

                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);
                }
            }
        }

        return new CommonsMultipartFile(item);
    }

    /**
     * 将流写入文件
     *
     * @param source
     * @param dest
     * @throws IOException
     */
    public static void streamToFile(InputStream source, File dest)
            throws IOException {
        OutputStream output = null;
        try {
            output = new FileOutputStream(dest);
            byte[] buf = new byte[1024];
            int bytesRead;
            while ((bytesRead = source.read(buf)) > 0) {
                output.write(buf, 0, bytesRead);
            }
        } catch (Exception e) {
            log.warn("", e);
            throw e;
        } finally {
            try {
                source.close();
                output.close();
            } catch (Exception e) {
                log.warn("", e);
            }
        }
    }


    public static String readTextFileContent(String filePathName) throws IOException {
        try (FileInputStream input = new FileInputStream(filePathName)){
            return readTextFileContent(input);
        }
    }

    public static String readTextFileContent(FileInputStream fileInputStream) throws IOException {
        String lines ="";
        try(InputStreamReader reader = new InputStreamReader(fileInputStream);
            BufferedReader br = new BufferedReader(reader)
        ) {

            StringBuilder lineb = new StringBuilder();
            String line;
            while((line = br.readLine()) != null) {
                lineb.append(line + "\n");
            }
            lines = lineb.toString();
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException var15) { }

        }
        return lines;
    }

    public static void bytesToFile(byte[] buf, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(buf);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 从网络Url中下载文件
     * @param urlStr
     * @param fileName
     * @param savePath
     * @throws IOException
     */
    public static void downLoadFromUrl(String urlStr,String fileName,String savePath) throws IOException{
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        //设置超时间为3秒
        conn.setConnectTimeout(3*1000);
        //防止屏蔽程序抓取而返回403错误
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        //得到输入流
        InputStream inputStream = conn.getInputStream();
        //获取自己数组
        byte[] getData = readInputStream(inputStream);

        //文件保存位置
        File saveDir = new File(savePath);
        if(!saveDir.exists()){
            saveDir.mkdir();
        }
        File file = new File(saveDir+File.separator+fileName);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(getData);
        if(fos!=null){
            fos.close();
        }
        if(inputStream!=null){
            inputStream.close();
        }

        System.out.println("info:"+url+" download success");
    }

    /**
     * 从输入流中获取字节数组
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static  byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    /**
     * response获取下载文件的流
     */
    public static void responseSetStream(String filePath,HttpServletResponse response) throws Exception{
        File file = new File(filePath);

        InputStream inputStream = null;
        OutputStream outputStream = null;
        if (file.exists()){
            try{
                inputStream = new FileInputStream(file);
                outputStream = new BufferedOutputStream(response.getOutputStream());
                byte[] bytes = new byte[1024];
                int len;
                while ((len = inputStream.read(bytes)) != -1){
                    outputStream.write(bytes,0,len);
                }
                outputStream.flush();
            }finally{
                if(null != outputStream){
                    outputStream.close();
                }
                if(null != inputStream){
                    inputStream.close();
                }

            }

        }
    }


    public static void downloadFile(String filePath, HttpServletRequest request,HttpServletResponse response) throws IOException {

        String s = filePath.substring(filePath.lastIndexOf("/") + 1);
        String filename = s.substring(s.indexOf("-") + 1);
        if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {
            // firefox浏览器
            filename = new String(filename.getBytes("UTF-8"), "ISO8859-1");
        } else {
            filename = URLEncoder.encode(filename, "UTF-8");
            filename=filename.replaceAll("\\+","%20");
        }
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
        FileInputStream in = new FileInputStream(filePath);
        ServletOutputStream out = response.getOutputStream();
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
        }
        out.flush();
        out.close();
        in.close();
    }

    /**
     * 文件批量下载成压缩文件
     *
     * @param response
     * @param files
     */
    public static void mutiDownloadFiles(HttpServletResponse response,List<File> files) throws Exception{
        String nowtime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String downloadFilename = nowtime+".zip";
        //指明response的返回对象是文件流
        response.setContentType("application/octet-stream");
        // 设置在下载框默认显示的文件名
        response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename );
        //设置压缩流：直接写入response，实现边压缩边下载
        ZipOutputStream zos = null;
        InputStream in = null;
        try {
            zos = new ZipOutputStream(response.getOutputStream());
            zos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法
            for (int i = 0; i < files.size(); i++) {
                File file = files.get(i);
                //添加ZipEntry，并ZipEntry中写入文件流
                //这里，加上i是防止要下载的文件有重名的导致下载失败
                String fileName = file.getName();
                String newFileName = fileName.substring(14);
                zos.putNextEntry(new ZipEntry(i + "-" + newFileName));
                in = new FileInputStream(file);
                byte[] buffer = new byte[100];
                int length = 0;
                while ((length = in.read(buffer)) != -1) {
                    zos.write(buffer, 0, length);
                }
                in.close();
            }
            zos.flush();

        }finally{
            if (zos!=null) {
                zos.close();
                zos.flush();
            }
            if (in!=null) {
                in.close();
            }
        }


    }

}
